---
sidebar_position: 2
title: Guide - Request Cancellation
sidebar_label: Cancellation
---

# Request Cancellation

Request cancellation is a crucial feature for managing data fetching in modern applications. It allows you to abort
ongoing requests to prevent race conditions, avoid unnecessary data processing, and improve user experience. Hyper-fetch
provides several ways to cancel requests, from automatic cancellation of stale requests to manual abortion when needed.

:::secondary What you'll learn

1.  How to automatically **cancel stale requests** to prevent race conditions.
2.  How to **manually abort** a request in TypeScript.
3.  The difference between **aborting** a request and **stopping** the dispatcher queue.
4.  How to **pause and resume** request queues.

:::

---

## Automatic Cancellation

When a user performs actions that trigger rapid, successive requests (like typing in a search bar), you can end up with
a "race condition"—a scenario where responses arrive out of order. For example, the response to an earlier request might
arrive after a later one, leading to an inconsistent UI state.

Hyper-fetch solves this with the `cancelable` option. When set to `true`, any new request will automatically cancel a
pending request made with the same `Request` instance.

```ts
// 1. Create a cancelable request
const searchUsers = client.createRequest()({
  endpoint: "/users",
  method: "GET",
  cancelable: true,
});

// 2. Simulate rapid search requests
// The first request will be sent
searchUsers.send({ queryParams: { search: "M" } });

setTimeout(() => {
  // 50ms later, this request will cancel the first one and be sent
  searchUsers.send({ queryParams: { search: "Ma" } });
}, 50);

setTimeout(() => {
  // 100ms later, this request will cancel the second one
  // Only the result for "Mac" will be processed
  searchUsers.send({ queryParams: { search: "Mac" } });
}, 100);
```

This ensures that only the most recent request's response is processed, keeping your application's data consistent.

---

## Manual Cancellation

There are times when you need to manually abort a request. For instance, a user might navigate away from a page while a
request is still pending, or click a "cancel" button on a file upload. Hyper-fetch provides an `abort` method on the
`request` instance.

In a non-React environment, you can call `abort` directly on the request instance you used to send the request.

```ts
const getUsers = client.createRequest()({
  endpoint: "/users",
  method: "GET",
});

// 1. Make a request
// highlight-next-line
getUsers.send();

setTimeout(() => {
  // 2. Abort it before it completes
  // highlight-next-line
  getUsers.abort();
}, 50);
```

or via RequestManager

```ts
import { client } from "./client";

const getUsers = client.createRequest()({
  endpoint: "/users",
  method: "GET",
});

// 1. Make a request
// highlight-next-line
getUsers.send();

setTimeout(() => {
  // 2. Abort it before it completes
  // highlight-next-line
  client.requestManager.abortByKey(getUsers.abortKey);
}, 50);
```

RequestManager also holds the AbortController for each request. You can access it via the `abortController` property.

```ts
// Map<abortKey, Map<requestId, AbortController>>
// highlight-next-line
client.requestManager.abortControllers;

// Get map of all requests with the same abortKey
// highlight-next-line
client.requestManager.abortControllers.get(getUsers.abortKey);

// Get single request abort controller
// highlight-next-line
client.requestManager.abortControllers.get(getUsers.abortKey)?.get(getUsers.requestId);
```

<LinkCard
  type="guides"
  title="How to get requestId?"
  description="Learn how to get requestId on example."
  to="/docs/guides/core/basics/fetching#how-to-get-requestid"
/>

---

## Pausing and Resuming Queues

Aborting a request terminates it. But what if you want to temporarily pause requests without losing them? This is common
in offline-first applications where you want to queue requests while offline and send them once the connection is
restored.

The `FetchDispatcher` allows you to `stop` and `start` its request queues. Stopping a queue prevents new requests from
being sent but keeps them in storage. Starting the queue resumes the dispatching process.

You can control queues using the `queueKey` of a request, which defaults to its `endpoint`.

```ts
const postFile = client.createRequest()({
  method: "POST",
  endpoint: "/files", // This is the default queueKey
  offline: true, // The request must be marked as offline to be queued
});

// This request will be queued if offline
postFile.send({ data: { some: "data" } });

// Later, you can stop the entire "/files" queue
// This will pause all requests targeting this endpoint
client.fetchDispatcher.stop(postFile.queueKey);

// And resume it when ready (e.g., when back online)
client.fetchDispatcher.start(postFile.queueKey);
```

:::caution Important

`stop` does not affect requests that are already in progress. It only prevents new requests in the queue from being
dispatched.

:::

---

:::success Congratulations!

You've learned how to effectively cancel and manage requests in Hyper-fetch!

- You can automatically **cancel stale requests** using the `cancelable: true` option to prevent race conditions.
- You can **manually abort** a request using the `.abort()` method on the request instance.
- You know the difference between **aborting a request** (terminating it) and **stopping a queue** (pausing it).
- You can **pause and resume** request dispatching using `client.fetchDispatcher.stop()` and
  `client.fetchDispatcher.start()`.

:::
